package com.fire.control.system.config.redis;

import java.lang.management.ManagementFactory;
import java.util.List;
import java.util.concurrent.TimeUnit;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.dao.DataAccessException;
import org.springframework.data.redis.connection.RedisConnection;
import org.springframework.data.redis.core.HashOperations;
import org.springframework.data.redis.core.RedisCallback;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.RedisSerializer;
import org.springframework.stereotype.Component;

import com.fire.control.system.statics.Key;
import com.fire.control.system.support.util.JSONUtil;

@Component("redisService")
public class RedisService{  
	
    @Autowired  
    private RedisTemplate<String, ?> redisTemplate;  
    @Autowired 
    private HashOperations<String, String, Object> hashOperations;
    
    public boolean lock(final String key){
    	//当前进程pid+name
    	String thisPid = ManagementFactory.getRuntimeMXBean().getName();
    	boolean result = redisTemplate.execute(new RedisCallback<Boolean>() {  
            @Override
            public Boolean doInRedis(RedisConnection connection) throws DataAccessException {
                RedisSerializer<String> serializer = redisTemplate.getStringSerializer();
                boolean result = connection.setNX(serializer.serialize(key), serializer.serialize(thisPid));
                if(!result){
                	//没拿到锁的服务器释放锁
                	unlock(key);
                }else{
                	//拿到锁的服务器设置锁的过期时间,防止因异常情况无法释放锁而造成死锁情况的发生
                	expire(key, Key.redis_key_lora_lock_.getExpire());
                }
                return result;
            }
        });
    	return result;
    }
    
    public void unlock(final String key){
    	redisTemplate.delete(key);
    }
     
    private boolean set(final String key, final String value) {  
        boolean result = redisTemplate.execute(new RedisCallback<Boolean>() {  
            @Override  
            public Boolean doInRedis(RedisConnection connection) throws DataAccessException {  
                RedisSerializer<String> serializer = redisTemplate.getStringSerializer();  
                connection.set(serializer.serialize(key), serializer.serialize(value));  
                return true;  
            }  
        });  
        return result;  
    } 
    
    public boolean set(final String key, final String value,long expire) {  
        boolean result = redisTemplate.execute(new RedisCallback<Boolean>() {  
            @Override  
            public Boolean doInRedis(RedisConnection connection) throws DataAccessException {  
                RedisSerializer<String> serializer = redisTemplate.getStringSerializer();  
                connection.set(serializer.serialize(key), serializer.serialize(value));  
                expire(key, expire);
                return true;  
            }  
        });  
        return result;  
    } 
  
    public String get(final String key){  
        String result = redisTemplate.execute(new RedisCallback<String>() {  
            @Override  
            public String doInRedis(RedisConnection connection) throws DataAccessException {  
                RedisSerializer<String> serializer = redisTemplate.getStringSerializer();  
                byte[] value =  connection.get(serializer.serialize(key));  
                return serializer.deserialize(value);  
            }  
        });  
        return result;  
    }  
  
    
    /**
    * @Title: expire
    * @Description: TODO(设置KEY过期时间(单位:秒),传入 -1 时表示不设置过期时间)
    * @author wanbo
    * @date  2017年6月14日 上午10:55:20
    * @param key
    * @param expire
    * @return
    */
    public boolean expire(final String key, long expire) {
        return redisTemplate.expire(key, expire, TimeUnit.SECONDS);  
    }  
  
    
    /**
    * @Title: setList
    * @Description: TODO(缓存集合)
    * @author wanbo
    * @date  2017年6月14日 上午10:55:30
    * @param key
    * @param list
    * @return
    */
    private <T> boolean setList(String key, List<T> list) {  
        String value = JSONUtil.toJson(list);  
        return set(key,value);  
    }  
    
    public <T> boolean setList(String key, List<T> list,long expire) {  
        String value = JSONUtil.toJson(list);  
        boolean b = set(key,value);  
        expire(key, expire);
        return b;
    }  
    
    public <T> boolean setObject(String key, Object obj) {  
        String value = JSONUtil.toJson(obj);  
        return set(key,value);  
    }  
    
    public <T> boolean setObject(String key, Object obj,long expire) {  
        String value = JSONUtil.toJson(obj);
        boolean b = set(key,value);  
        expire(key, expire);
        return b;
    }  
  
      
    public <T> List<T> getList(String key,Class<T> clz) {  
        String json = get(key);  
        if(json!=null){  
            List<T> list = JSONUtil.toList(json, clz);  
            return list;  
        }  
        return null;  
    }  
    
    public <T> T getObject(String key,Class<T> clz) {  
        String json = get(key);  
        if(json!=null){  
        	T obj =  JSONUtil.toBean(json, clz);  
            return obj;  
        }  
        return null;  
    }  
  
      
    /**
    * @Title: lpush
    * @Description: TODO(
    * 在保存在key列表的头部插入所有指定的值。
    * 如果key不存在，则执行推操作之前创建的空列表。
    * 当key持有的值不是列表，则返回一个错误。 
    * 返回值 返回整数 - 推送操作后列)
    * @author wanbo
    * @date  2017年6月14日 上午11:20:22
    * @param key
    * @param obj
    * @return
    */
    public long lpush(final String key, Object obj) {  
        final String value = JSONUtil.toJson(obj);  
        long result = redisTemplate.execute(new RedisCallback<Long>() {  
            @Override  
            public Long doInRedis(RedisConnection connection) throws DataAccessException {  
                RedisSerializer<String> serializer = redisTemplate.getStringSerializer();  
                long count = connection.lPush(serializer.serialize(key), serializer.serialize(value));  
                return count;  
            }  
        });  
        return result;  
    }  
  
      
    /**
    * @Title: rpush
    * @Description: TODO(
    * 插入所有指定的值，在存储在列表的key尾部。
    * 如果键不存在，则执行压栈操作之前创建的空列表。
    * 当key持有的值不是列表，则返回一个错误。 
    * 返回值 返回整数，压栈操作后)
    * @author wanbo
    * @date  2017年6月14日 上午11:19:10
    * @param key
    * @param obj
    * @return
    */
    public long rpush(final String key, Object obj) {  
        final String value = JSONUtil.toJson(obj);  
        long result = redisTemplate.execute(new RedisCallback<Long>() {  
            @Override  
            public Long doInRedis(RedisConnection connection) throws DataAccessException {  
                RedisSerializer<String> serializer = redisTemplate.getStringSerializer();  
                long count = connection.rPush(serializer.serialize(key), serializer.serialize(value));  
                return count;  
            }  
        });  
        return result;  
    }  
  
    
    /**
    * @Title: lpop
    * @Description: TODO(删除第一个元素，并返回保存列表在key的第一个元素)
    * @author wanbo
    * @date  2017年6月14日 上午11:13:30
    * @param key
    * @return
    */
    public String lpop(final String key) {  
        String result = redisTemplate.execute(new RedisCallback<String>() {  
            @Override  
            public String doInRedis(RedisConnection connection) throws DataAccessException {  
                RedisSerializer<String> serializer = redisTemplate.getStringSerializer();  
                byte[] res =  connection.lPop(serializer.serialize(key));  
                return serializer.deserialize(res);  
            }  
        });  
        return result;  
    }  
    
  
}  